home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Interactive 7
/
PC World Interactive 7.iso
/
program
/
cprog.EXE
/
OBJ2ASM.ZIP
/
OMAIN.C
< prev
next >
Wrap
Text File
|
1991-10-02
|
18KB
|
453 lines
/*
** OBJASM - Utility to create .ASM files out of .OBJ files.
** Options are:
**
** -r = Create RASM86 compatible output (.A86 instead of .ASM)
** -4 = Make compatible with MASM v4.0 (no retf)
** -a = Add labels for un-named data references
** -h = Hex output as comments
** -v = 486 instructions
** -s# = Minimum string size in data segment
** -c# = Minimum string size in code segment
** -f(filename) = Additional information filename (w/paren.)
**
** Includes 8086/80186/80286/80386/80486
** and 8087/80287/80387 coprocessor instructions
** See OBJASM.DOC for a more detailed description.
** (C) Copyright 1988,1989,1990,1991 by Robert F. Day, All rights reserved.
**
** Send/phone questions, comments, and bugs to:
**
** Robert F. Day
** 19906 Filbert Dr.
** Bothell, WA 98012
** (206) 481-8431
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <alloc.h>
#include "o.h"
/*--- Expanded INTEL OMF record types --*/
#define RHEADR 0x6E /* R-Module Header Record */
#define REGINT 0x70 /* Register Initialization Record */
#define REDATA 0x72 /* Relocatable Enumerated Data Record */
#define RIDATA 0x74 /* Relocatable Iterated Data Record */
#define OVLDEF 0x76 /* Overlay Definition Record */
#define ENDREC 0x78 /* End Record */
#define BLKREC 0x7A /* Block Definition Record */
#define BKLEND 0x7C /* Block End Record */
#define DEBSYM 0x7E /* Debug Symbols Record */
#define THEADR 0x80 /* x T-Module Header Record */
#define LHEADR 0x82 /* L-Module Header Record */
#define PEDATA 0x84 /* Physical Enumerated Data (?) */
#define PIDATA 0x86 /* Physical Iterated Data (?) */
#define COMENT 0x88 /* x Comment Record */
#define MODEND 0x8A /* x Module End Record */
#define MODENDL 0x8B /* l Module End Record */
#define EXTDEF 0x8C /* x External Names Definition Record */
#define TYPDEF 0x8E /* Type Definitions Record */
#define PUBDEF 0x90 /* x Public Names Definition Record */
#define PUBDEFL 0x91 /* l Public Names Definition Record */
#define LOCSYM 0x92 /* Local Symbols Record */
#define LINNUM 0x94 /* Line Numbers Record */
#define LNAMES 0x96 /* x List of Names Record */
#define SEGDEF 0x98 /* x Segment Definition Record */
#define SEGDEFL 0x99 /* l Segment Definition Record */
#define GRPDEF 0x9A /* x Group Definition Record */
#define FIXUPP 0x9C /* x Fix-Up Record */
#define FIXUPPL 0x9D /* l Fix-Up Record */
#define LEDATA 0xA0 /* x Logical Enumerated Data */
#define LEDATAL 0xA1 /* l Logical Enumerated Data */
#define LIDATA 0xA2 /* x Logical Iterated Data */
#define LIDATAL 0xA3 /* l Logical Iterated Data */
#define LIBHED 0xA4 /* Library Header Record */
#define LIBNAM 0xA6 /* Library Module Names Record */
#define LIBLOC 0xA8 /* Library Module Locations Record */
#define LIBDIC 0xAA /* Library Dictionary Record */
#define COMDEF 0xB0 /* m Communal Data Definition Record */
#define LEXTDEF 0xB4 /* m Local External Definition */
#define LPUBDEF 0xB6 /* m Local Public Definition */
#define LPUBDF2 0xB7 /* m Local Public Definition (2nd case?)*/
#define LCOMDEF 0xB8 /* m Local Communal Data Definition */
#define LIBHDR 0xF0 /* m Library Header Record */
#define LIBEND 0xF1 /* m Library Trailer Record */
/* x = Intel OMF used by Microsoft */
/* m = Microsoft Additions to Intel OMF */
/* l = Later extensions by Microsoft */
/*
** Local Prototypes
*/
int main( int, char *[] );
FILE *o_file; /* .OBJ file that we are processing */
long o_position; /* Position in file of current data */
NODE_T *line_tree;
NODE_T *arg_scope_tree;
NODE_T *loc_scope_tree;
NODE_T *end_scope_tree;
NODE_T *name_tree;
NODE_T *segment_tree;
NODE_T *group_tree;
NODE_T *public_tree;
NODE_T *extern_tree;
NODE_T *sex_tree;
NODE_T *data_tree;
NODE_T *struc_tree;
NODE_T *fix_tree;
NODE_T *hint_tree;
NODE_T *type_tree;
NODE_T *block_tree;
SEG_T *seg_rec;
SEG_T seg_search;
GRP_T grp_search;
NODE_T *pub_node;
PUB_T *pub_rec;
PUB_T *last_pub_rec;
PUB_T pub_search;
NODE_T *hint_node;
HINT_T *hint_rec;
HINT_T hint_search;
THREAD_T threads[2][4] = {0};
NODE_T *fix_node;
FIX_T *fix_rec;
FIX_T fix_search;
NAME_T name_search;
int label_count = 0;
int segment;
dword inst_offset;
int processor_mode = 0;
int segment_mode;
int segment_bytes;
char *cseg_name;
PUB_T *start_pub = NULL;
word code_string = 40; /* Stringizing Limit in Code */
word data_string = 3; /* Stringizing Limit in Data */
int pass; /* 1=Building Labels, 2=Generating Output */
int processor_type_comment_occurred = FALSE; /* No processor spec yet */
int hex_finish; /* For hex comments */
int tab_offset = 0; /* Current tab offset, 0 = none */
int compatibility = 0; /* 0 = MASM 5.0+ (Microsoft) */
/* 1 = MASM 4.0 (Microsoft) */
/* 2 = RASM86 (Digital Research) */
int add_labels = FALSE; /* No, treat as .obj translator */
/* Otherwise, treat as .asm creator */
/* Translator is a strict translation */
int hex_output = FALSE; /* Display hex code as comments? */
char extra_filename[65] = {'\0'};/* Additional information file */
/*
** ------- Exit values -------- **
** 0 = Successful operation **
** 1 = Improper Usage **
** 2 = Unable to open OBJ file **
** 3 = Premature end of file **
** 4 = Out of memory **
** 5 = .OBJ Format error **
** 6 = Unable to open ADD file **
** 7 = Syntax error in ADD file **
** ------- Exit values -------- **
*/
int main( argc, argv )
int argc;
char *argv[];
{
char *argp;
int name_arg;
int argi;
int bad_args;
char *fnamep;
dword position;
int at_eof;
int rec_type;
word rec_length;
char temp_name[50];
char ch;
int i486;
bad_args = FALSE;
argi = 1;
name_arg = 0;
i486 = FALSE;
while ( argi < argc ) {
argp = argv[argi];
if ( *argp++ == '-' ) {
while ( *argp ) {
switch ( *argp ) {
case 'a':
add_labels = TRUE;
break;
case '4':
compatibility = 1;
break;
case 'r':
compatibility = 2;
break;
case 'h':
hex_output = TRUE;
break;
case 'v':
i486 = TRUE;
break;
case 'c':
code_string = atoi(argp+1);
while ( (ch = *(argp+1)) != '\0' ) {
if ( ch < '0' || ch > '9' ) {
break;
}
argp++;
}
break;
case 's':
code_string = atoi(argp+1);
while ( (ch = *(argp+1)) != '\0' ) {
if ( ch < '0' || ch > '9' ) {
break;
}
argp++;
}
break;
case 'f':
argp++;
if ( *argp != '(' ) {
bad_args = TRUE;
break;
}
fnamep = extra_filename;
while ( (ch = *(argp+1)) != '\0' ) {
argp++;
if ( ch == ')' ) {
*fnamep = '\0';
break;
}
*fnamep++ = ch;
}
if ( ch == '\0' ) {
bad_args = TRUE;
}
break;
default:
bad_args = TRUE;
break;
}
argp++;
}
} else {
if ( name_arg == 0 ) {
name_arg = argi;
} else {
bad_args = TRUE;
}
}
argi++;
}
if ( name_arg == 0 ) {
bad_args = TRUE;
}
if ( bad_args ) {
fprintf( stderr, "Usage: %s [-options] [objfilename]\n", argv[0] );
fprintf( stderr, "where -options are:\n" );
fprintf( stderr, " -4 Make MASM 4.0 compatible (no RETF)\n" );
fprintf( stderr, " -a Add labels for un-named data references\n");
fprintf( stderr, " -h Hex output in comments\n");
fprintf( stderr, " -r Make RASM86 compatible\n" );
fprintf( stderr, " -v Include 486 instructions\n" );
fprintf( stderr, " -c# Minimum string size in a code segment (default=40)\n");
fprintf( stderr, " -s# Mimimum string size in a data segment (default=3)\n");
fprintf( stderr, " -f(filename) Additional information filename (w/paren.)\n");
fprintf( stderr, "\n" );
fprintf( stderr, "Additional information file lines:\n");
fprintf( stderr, "SEG sname CODE named segment is a code segment\n");
fprintf( stderr, "SEG sname DATA named segment is a data segment\n");
fprintf( stderr, "var=sname:#### creates a local label in segment name\n");
fprintf( stderr, "sname:####:DB/DW/DD/DF/DQ/DT directs dis-assembly into data\n");
fprintf( stderr, "... (for more info, read OBJASM.DOC)\n");
exit(1);
}
switch( compatibility ) {
case 0: /* MASM 5.0+ */
if ( i486 ) {
ex_instr[0x08].text = "invd";
ex_instr[0x09].text = "wbinvd";
op_grp[6][7] = "invlpg";
ex_instr[0xA6].text = "cmpxchg";
ex_instr[0xA7].text = "cmpxchg";
ex_instr[0xC0].text = "xadd";
ex_instr[0xC1].text = "xadd";
ex_instr[0xC8].text = "bswap";
ex_instr[0xC9].text = "bswap";
ex_instr[0xCA].text = "bswap";
ex_instr[0xCB].text = "bswap";
ex_instr[0xCC].text = "bswap";
ex_instr[0xCD].text = "bswap";
ex_instr[0xCE].text = "bswap";
ex_instr[0xCF].text = "bswap";
}
break;
case 1: /* MASM 4.0 */
/*
** Make far return only a comment
*/
instr[0xCB].text = "ret\t; (retf)";
break;
case 2: /* RASM86 */
/*
** Make xlat a xlat bx
*/
instr[0xD7].text = "xlat\tbx";
/*
** Make short jmp a jmps
*/
instr[0xEB].text = "jmps";
/*
** Make far jmp a jmpf
*/
op_grp[4][5] = "jmpf";
break;
}
strcpy( temp_name, argv[name_arg] );
if ( strchr(temp_name,'.') == NULL ) { /* Append ".obj" if no extension */
strcat( temp_name, ".obj" ); /* is supplied */
}
o_file = fopen( temp_name, "rb" );
if ( o_file == NULL ) {
fprintf( stderr, "%s: Cannot open %s\n", argv[0], temp_name );
exit(2);
}
/* Print copyright message */
printf("; OBJASM version 2.0 released on Jan 3, 1991\n");
printf("; (C) Copyright 1988,1989,1990,1991 by Robert F. Day. All rights reserved\n\n");
init_trees(); /* Initialize all trees */
at_eof = FALSE;
position = 0;
while ( !at_eof ) {
fseek( o_file, position, L_SET );
rec_type = fgetc( o_file );
if ( rec_type == EOF ) {
at_eof = TRUE;
} else {
rec_length = getw( o_file );
o_position = position + 3; /* (1 rec_type) + (2 rec_length) */
#ifdef DEBUG
printf("PROCESSING rec_type [%02X] rec_length [%04X]\n",
rec_type, rec_length );
#endif
switch( rec_type ) {
case THEADR: theadr(); break;
case LNAMES: lnames( rec_length ); break;
case GRPDEF: grpdef( rec_length ); break;
case SEGDEF: segdef(); break;
case SEGDEFL: segdef(); break;
case PUBDEF: pubdef( rec_length, TRUE ); break;
case PUBDEFL: pubdef( rec_length, TRUE ); break;
case LPUBDEF: pubdef( rec_length, FALSE ); break;
case LPUBDF2: pubdef( rec_length, FALSE ); break;
case EXTDEF: extdef( rec_length, TRUE ); break;
case LEXTDEF: extdef( rec_length, FALSE ); break;
case LEDATA: ledata( rec_length, REGULAR ); break;
case LEDATAL: ledata( rec_length, LARGER ); break;
case LIDATA: lidata( rec_length, REGULAR ); break;
case LIDATAL: lidata( rec_length, LARGER ); break;
case FIXUPP: fixupp( rec_length, REGULAR ); break;
case FIXUPPL: fixupp( rec_length, LARGER ); break;
case COMDEF: comdef( rec_length, TRUE ); break;
case LCOMDEF: comdef( rec_length, FALSE ); break;
case MODEND: modend( rec_length, REGULAR );
at_eof = TRUE; break;
case MODENDL: modend( rec_length, LARGER );
at_eof = TRUE; break;
case TYPDEF: break;
case COMENT: printf("; [%04X]",position);
coment( rec_length ); break;
case LINNUM: linnum( rec_length ); break;
default: printf( "Bad record type: [%08lX:%02X:%04X]\n",
position, rec_type, rec_length );
break;
}
position += 3 + rec_length;
}
}
#ifdef DEBUG
printf("PROCESSING dis-assembly, pass 1\n");
#endif
if ( strlen(extra_filename) != 0 ) {
load_extra( argv[0], extra_filename );
}
pass = 1;
process(); /* First pass: Processing */
pass = 2;
process(); /* Second pass: Figure out labels */
#ifdef DEBUG
printf("PROCESSING listing externals\n");
#endif
list_ext(); /* Show EXTERNAL's */
#ifdef DEBUG
printf("PROCESSING listing publics and communal definitions\n");
#endif
list_pub(); /* Show PUBLIC's */
list_struc(); /* Show STRUC's */
#ifdef DEBUG
printf("PROCESSING dis-assembly, pass 2 (last)\n");
#endif
pass = 3;
process(); /* Third pass: Output */
fclose( o_file );
#ifdef DEBUG
printf("END OF RUN\n");
#endif
return(0);
}